package com.anivia.common.log.filter;

import com.anivia.common.log.AniviaRequestWrapper;
import com.anivia.common.log.AniviaResponseWrapper;
import com.anivia.common.log.RequestLogHandler;
import com.anivia.common.log.util.HttpWrapperUtil;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;


/**
 * @author wangj
 */
@Slf4j
public class RequestLogFilter implements Filter {
    /**
     * 支持记录日志的请求方式
     */
    private static List<String> methods;
    private final RequestLogHandler requestLogHandler;

    public RequestLogFilter(RequestLogHandler requestLogHandler) {
        this.requestLogHandler = requestLogHandler;
        this.methods = Arrays.asList("GET", "POST");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 判断请求和响应是否为HttpServletRequest和HttpServletResponse，并且请求方法在methods集合中
        if (request instanceof HttpServletRequest && response instanceof HttpServletResponse
                && methods.contains(((HttpServletRequest) request).getMethod().toUpperCase())) {
            HttpServletRequest requestWrapper = (HttpServletRequest) request;
            // 判断是否需要获取请求体
            if (HttpWrapperUtil.isGetBody(requestWrapper)) {
                requestWrapper = AniviaRequestWrapper.build(requestWrapper);
            }
            // 构建AniviaResponseWrapper响应包装器
            AniviaResponseWrapper responseWrapper = AniviaResponseWrapper.build((HttpServletResponse) response);
            // 初始化请求日志处理器
            requestLogHandler.init(requestWrapper);
            try {
                // 执行FilterChain链中的过滤器
                chain.doFilter(requestWrapper, responseWrapper);
            } finally {
                // 打印请求日志
                requestLogHandler.printLog(requestWrapper, responseWrapper);
                // 销毁请求和响应包装器，并输出响应体
                HttpWrapperUtil.destroy((HttpServletRequest) request, (HttpServletResponse) response,
                        requestWrapper, responseWrapper, responseWrapper.getResponseBody());
            }
        } else {
            // 如果不满足条件，直接执行FilterChain链中的过滤器
            chain.doFilter(request, response);
        }
    }
}
